package com.sanbuTech.foundation.manager;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.sanbuTech.foundation.exception.SanbuFoudationException;
import com.sanbuTech.foundation.manager.base.BaseManager;

@Component("idTableManager")
public class IdTableManager extends BaseManager{

	private static Logger logger = LoggerFactory.getLogger(IdTableManager.class);
	
	private final String mapper = "com.sanbuTech.blank.dao.IdTableMapperDao.";
	
	@Value("#{'${id.start}'}")
	private int start;		//id初始值

	@Value("#{'${id.increment}'}")
	private int increment;		//id增量
	
	private final static String START_KEY =  "foudation:startId";
	private final static String END_KEY =  "foudation:endId";
	
	public synchronized long getAvailableId() throws SanbuFoudationException{
		long returnId = 0l;
		
		long startId = 0l;
		long endId = 0l;
		
		String startId_fromCache = shardJededis.get(START_KEY);
		String endId_fromCache = shardJededis.get(END_KEY);
		
		logger.info("startId_fromCache: " + startId_fromCache);
		logger.info("endId_fromCache: " + endId_fromCache);
		
		//缓存没有, 从数据库获取
		if(StringUtils.isEmpty(startId_fromCache) || startId_fromCache == "0"){
			
			long maxId = this.getMaxEndId();
			
			logger.info("maxId from database: " + maxId);
			
			if(maxId == 0l){
				startId = start;		//连数据库都没有值, 写入id初始值
				endId = startId + increment;
				//数据库没数据, 表示是初始数据, 需要插入最新一条
				int i = this.insertOne(startId, endId);
				if(i == 0){
					throw new SanbuFoudationException("cannot insert id value in foudation database.");
				}
			}else{
				startId = maxId + 1;
				endId = startId + increment;
			}
			
			logger.info("startId: " + startId);
			
			//只要是重新从数据库获取, 都要更新缓存数据
			shardJededis.set(START_KEY, String.valueOf(startId+1));
			shardJededis.set(END_KEY, String.valueOf(endId));
			
			returnId = startId;
		}else{
			startId = Long.valueOf(startId_fromCache);
			endId = Long.valueOf(endId_fromCache);
			
			if(startId > endId){
				//TODO 这种不科学的结果, 需要处理一下
			}
			
			if(startId <= endId){
				//id可用, 直接
				returnId = startId;
				//缓存+1
				shardJededis.incr(START_KEY);
				
				 if(startId == endId){
					 
					 //本批最后一个有效id使用了, 需要在id库记录下一批有效id范围
					 startId += 1;
					 endId = startId + increment;
					//把新的一批写入库
					int i = this.insertOne(startId, endId);
					if(i == 0){
						throw new SanbuFoudationException("cannot insert id value in foudation database.");
					}
					
					logger.info("startId == endId, 新一批id入库和写入缓存");
					logger.info("next startId: "+ startId);
					logger.info("next endId: "+ endId);
					
					shardJededis.set(START_KEY, String.valueOf(startId));
					shardJededis.set(END_KEY, String.valueOf(endId));
				}
			}
		}
		
		return returnId;
	}
	
	//获取最大的旧id数值
	public long getMaxEndId(){
		long id_re = 0l;
		Long id = dao.queryUnique(mapper+"queryMaxEndId", new HashMap<String, Object>());
		if(id != null){
			id_re = id;
		}
		return id_re;
	}
	
	
	public int insertOne(long startId, long endId){
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("startId", startId);
		params.put("endId", endId);
		return dao.insertAndReturnAffectedCount(mapper+"insertOne", params);
	}
	
	
}
